package com.how.config.base;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.api.config.masterslave.LoadBalanceStrategyConfiguration;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.NoneShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;

import javax.sql.DataSource;
import java.util.*;

public abstract class DataSourceBase {

    public static final String BASEDATABASE = "base";
    public static final String CONSOLEDATABASE = "console";

    public static ShardingRuleConfiguration getShardingRuleConfiguration(String defaultDataSourceName) {
        //具体分库分表策略
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        // 不分库分表情况下的数据源制定--默认数据库
        shardingRuleConfig.setDefaultDataSourceName(defaultDataSourceName);
        // 默认的分表规则
        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        // 默认的分库规则
        shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        // 指定表的主键生成策略为SNOWFLAKE
        shardingRuleConfig.setDefaultKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "id"));

        return shardingRuleConfig;
    }

    public static List<String> getSlaveDataSourceNames(ShardingDataSource shardingDataSource, String dataBase) {
        Map<String, DataSource> dataSourceMap = shardingDataSource.getDataSourceMap();
        Set<String> keySet = dataSourceMap.keySet();
        HashMap<String, DataSource> map = Maps.newHashMap();
        List<String> slaveDataSourceNames = Lists.newArrayList();
        for (String s : keySet) {
            if (s.startsWith(dataBase)) {
                if (s.contains("slave")) {
                    slaveDataSourceNames.add(s);
                }
            }
        }
        return slaveDataSourceNames;
    }

    public static MasterSlaveRuleConfiguration getMasterSlaveRuleConfiguration(ShardingDataSource shardingDataSource, String dataBase) {
        List<String> slaveDataSourceNames = getSlaveDataSourceNames(shardingDataSource, dataBase);

        return new MasterSlaveRuleConfiguration(dataBase, dataBase,
                // 从库集合
                slaveDataSourceNames,
                // 轮训策略
                new LoadBalanceStrategyConfiguration("round_robin"));
    }

    public static TableRuleConfiguration getTableRuleConfigurations(
            String tableName, String shardingColumn, String actualDataNodes,
            String tableAlgorithmExpression, String dataBaseAlgorithmExpression, String keyGenerator) {

        TableRuleConfiguration ruleConfiguration = new TableRuleConfiguration(tableName, actualDataNodes);
        // 表策略
        if (StringUtils.isNotBlank(tableAlgorithmExpression)) {
            ruleConfiguration.setTableShardingStrategyConfig(
                    new InlineShardingStrategyConfiguration(shardingColumn, tableAlgorithmExpression));
        } else {
            ruleConfiguration.setTableShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        }
        // 分库策略:不分库
        if (StringUtils.isNotBlank(dataBaseAlgorithmExpression)) {
            ruleConfiguration.setDatabaseShardingStrategyConfig(
                    new InlineShardingStrategyConfiguration(shardingColumn, dataBaseAlgorithmExpression));
        } else {
            ruleConfiguration.setDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        }

        // 指定表的主键生成策略为SNOWFLAKE
        if (StringUtils.isNotBlank(keyGenerator)) {
            ruleConfiguration.setKeyGeneratorConfig(new KeyGeneratorConfiguration(keyGenerator, shardingColumn));
        }

        return ruleConfiguration;
    }

    // 配置
    public static Properties getProperties() {
        Properties properties = new Properties();
        //是否打印SQL解析和改写日志
        properties.setProperty("sql.show", Boolean.TRUE.toString());
        //用于SQL执行的工作线程数量，为零则表示无限制
        properties.setProperty("executor.size", "4");
        //每个物理数据库为每次查询分配的最大连接数量
        properties.setProperty("max.connections.size.per.query", "1");
        //是否在启动时检查分表元数据一致性
        properties.setProperty("check.table.metadata.enabled", "false");
        return properties;
    }
}
